<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Cascade Classifier</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d9/df8/tutorial_root.html">OpenCV Tutorials</a></li><li class="navelem"><a class="el" href="../../d3/dd5/tutorial_table_of_content_other.html">Other tutorials (ml, objdetect, photo, stitching, video)</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Cascade Classifier </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><b>Prev Tutorial:</b> <a class="el" href="../../d4/dee/tutorial_optical_flow.html">Optical Flow</a></p>
<p><b>Next Tutorial:</b> <a class="el" href="../../dc/d88/tutorial_traincascade.html">Cascade Classifier Training</a></p>
<table class="doxtable">
<tr>
<th align="right"></th><th align="left"></th></tr>
<tr>
<td align="right">Original author </td><td align="left">Ana Huamán </td></tr>
<tr>
<td align="right">Compatibility </td><td align="left">OpenCV &gt;= 3.0 </td></tr>
</table>
<h2>Goal </h2>
<p>In this tutorial,</p>
<ul>
<li>We will learn how the Haar cascade object detection works.</li>
<li>We will see the basics of face detection and eye detection using the Haar Feature-based Cascade Classifiers</li>
<li>We will use the <a class="el" href="../../d1/de5/classcv_1_1CascadeClassifier.html">cv::CascadeClassifier</a> class to detect objects in a video stream. Particularly, we will use the functions:<ul>
<li><a class="el" href="../../d1/de5/classcv_1_1CascadeClassifier.html#a1a5884c8cc749422f9eb77c2471958bc">cv::CascadeClassifier::load</a> to load a .xml classifier file. It can be either a Haar or a LBP classifier</li>
<li><a class="el" href="../../d1/de5/classcv_1_1CascadeClassifier.html#aaf8181cb63968136476ec4204ffca498">cv::CascadeClassifier::detectMultiScale</a> to perform the detection.</li>
</ul>
</li>
</ul>
<h2>Theory </h2>
<p>Object Detection using Haar feature-based cascade classifiers is an effective object detection method proposed by Paul Viola and Michael Jones in their paper, "Rapid Object Detection using a
Boosted Cascade of Simple Features" in 2001. It is a machine learning based approach where a cascade function is trained from a lot of positive and negative images. It is then used to detect objects in other images.</p>
<p>Here we will work with face detection. Initially, the algorithm needs a lot of positive images (images of faces) and negative images (images without faces) to train the classifier. Then we need to extract features from it. For this, Haar features shown in the below image are used. They are just like our convolutional kernel. Each feature is a single value obtained by subtracting sum of pixels under the white rectangle from sum of pixels under the black rectangle.</p>
<div class="image">
<img src="../../haar_features.jpg" alt="haar_features.jpg"/>
<div class="caption">
image</div></div>
<p> Now, all possible sizes and locations of each kernel are used to calculate lots of features. (Just imagine how much computation it needs? Even a 24x24 window results over 160000 features). For each feature calculation, we need to find the sum of the pixels under white and black rectangles. To solve this, they introduced the integral image. However large your image, it reduces the calculations for a given pixel to an operation involving just four pixels. Nice, isn't it? It makes things super-fast.</p>
<p>But among all these features we calculated, most of them are irrelevant. For example, consider the image below. The top row shows two good features. The first feature selected seems to focus on the property that the region of the eyes is often darker than the region of the nose and cheeks. The second feature selected relies on the property that the eyes are darker than the bridge of the nose. But the same windows applied to cheeks or any other place is irrelevant. So how do we select the best features out of 160000+ features? It is achieved by <b>Adaboost</b>.</p>
<div class="image">
<img src="../../haar.png" alt="haar.png"/>
<div class="caption">
image</div></div>
<p> For this, we apply each and every feature on all the training images. For each feature, it finds the best threshold which will classify the faces to positive and negative. Obviously, there will be errors or misclassifications. We select the features with minimum error rate, which means they are the features that most accurately classify the face and non-face images. (The process is not as simple as this. Each image is given an equal weight in the beginning. After each classification, weights of misclassified images are increased. Then the same process is done. New error rates are calculated. Also new weights. The process is continued until the required accuracy or error rate is achieved or the required number of features are found).</p>
<p>The final classifier is a weighted sum of these weak classifiers. It is called weak because it alone can't classify the image, but together with others forms a strong classifier. The paper says even 200 features provide detection with 95% accuracy. Their final setup had around 6000 features. (Imagine a reduction from 160000+ features to 6000 features. That is a big gain).</p>
<p>So now you take an image. Take each 24x24 window. Apply 6000 features to it. Check if it is face or not. Wow.. Isn't it a little inefficient and time consuming? Yes, it is. The authors have a good solution for that.</p>
<p>In an image, most of the image is non-face region. So it is a better idea to have a simple method to check if a window is not a face region. If it is not, discard it in a single shot, and don't process it again. Instead, focus on regions where there can be a face. This way, we spend more time checking possible face regions.</p>
<p>For this they introduced the concept of <b>Cascade of Classifiers</b>. Instead of applying all 6000 features on a window, the features are grouped into different stages of classifiers and applied one-by-one. (Normally the first few stages will contain very many fewer features). If a window fails the first stage, discard it. We don't consider the remaining features on it. If it passes, apply the second stage of features and continue the process. The window which passes all stages is a face region. How is that plan!</p>
<p>The authors' detector had 6000+ features with 38 stages with 1, 10, 25, 25 and 50 features in the first five stages. (The two features in the above image are actually obtained as the best two features from Adaboost). According to the authors, on average 10 features out of 6000+ are evaluated per sub-window.</p>
<p>So this is a simple intuitive explanation of how Viola-Jones face detection works. Read the paper for more details or check out the references in the Additional Resources section.</p>
<h2>Haar-cascade Detection in OpenCV </h2>
<p>OpenCV provides a training method (see <a class="el" href="../../dc/d88/tutorial_traincascade.html">Cascade Classifier Training</a>) or pretrained models, that can be read using the <a class="el" href="../../d1/de5/classcv_1_1CascadeClassifier.html#a1a5884c8cc749422f9eb77c2471958bc">cv::CascadeClassifier::load</a> method. The pretrained models are located in the data folder in the OpenCV installation or can be found <a href="https://github.com/opencv/opencv/tree/master/data">here</a>.</p>
<p>The following code example will use pretrained Haar cascade models to detect faces and eyes in an image. First, a <a class="el" href="../../d1/de5/classcv_1_1CascadeClassifier.html">cv::CascadeClassifier</a> is created and the necessary XML file is loaded using the <a class="el" href="../../d1/de5/classcv_1_1CascadeClassifier.html#a1a5884c8cc749422f9eb77c2471958bc">cv::CascadeClassifier::load</a> method. Afterwards, the detection is done using the <a class="el" href="../../d1/de5/classcv_1_1CascadeClassifier.html#aaf8181cb63968136476ec4204ffca498">cv::CascadeClassifier::detectMultiScale</a> method, which returns boundary rectangles for the detected faces or eyes.</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'><p> This tutorial code's is shown lines below. You can also download it from <a href="https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp">here</a> </p><div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d8/da3/objdetect_8hpp.html">opencv2/objdetect.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d4/dd5/highgui_8hpp.html">opencv2/highgui.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">opencv2/imgproc.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../dc/d3d/videoio_8hpp.html">opencv2/videoio.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span>std;</div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> detectAndDisplay( <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> frame );</div><div class="line"></div><div class="line"><a class="code" href="../../d1/de5/classcv_1_1CascadeClassifier.html">CascadeClassifier</a> face_cascade;</div><div class="line"><a class="code" href="../../d1/de5/classcv_1_1CascadeClassifier.html">CascadeClassifier</a> eyes_cascade;</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main( <span class="keywordtype">int</span> argc, <span class="keyword">const</span> <span class="keywordtype">char</span>** argv )</div><div class="line">{</div><div class="line">    <a class="code" href="../../d0/d2e/classcv_1_1CommandLineParser.html">CommandLineParser</a> parser(argc, argv,</div><div class="line">                             <span class="stringliteral">&quot;{help h||}&quot;</span></div><div class="line">                             <span class="stringliteral">&quot;{face_cascade|data/haarcascades/haarcascade_frontalface_alt.xml|Path to face cascade.}&quot;</span></div><div class="line">                             <span class="stringliteral">&quot;{eyes_cascade|data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|Path to eyes cascade.}&quot;</span></div><div class="line">                             <span class="stringliteral">&quot;{camera|0|Camera device number.}&quot;</span>);</div><div class="line"></div><div class="line">    parser.about( <span class="stringliteral">&quot;\nThis program demonstrates using the cv::CascadeClassifier class to detect objects (Face + eyes) in a video stream.\n&quot;</span></div><div class="line">                  <span class="stringliteral">&quot;You can use Haar or LBP features.\n\n&quot;</span> );</div><div class="line">    parser.printMessage();</div><div class="line"></div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> face_cascade_name = <a class="code" href="../../d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13">samples::findFile</a>( parser.get&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt;(<span class="stringliteral">&quot;face_cascade&quot;</span>) );</div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> eyes_cascade_name = <a class="code" href="../../d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13">samples::findFile</a>( parser.get&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt;(<span class="stringliteral">&quot;eyes_cascade&quot;</span>) );</div><div class="line"></div><div class="line">    <span class="comment">//-- 1. Load the cascades</span></div><div class="line">    <span class="keywordflow">if</span>( !face_cascade.<a class="code" href="../../d1/de5/classcv_1_1CascadeClassifier.html#a1a5884c8cc749422f9eb77c2471958bc">load</a>( face_cascade_name ) )</div><div class="line">    {</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;--(!)Error loading face cascade\n&quot;</span>;</div><div class="line">        <span class="keywordflow">return</span> -1;</div><div class="line">    };</div><div class="line">    <span class="keywordflow">if</span>( !eyes_cascade.<a class="code" href="../../d1/de5/classcv_1_1CascadeClassifier.html#a1a5884c8cc749422f9eb77c2471958bc">load</a>( eyes_cascade_name ) )</div><div class="line">    {</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;--(!)Error loading eyes cascade\n&quot;</span>;</div><div class="line">        <span class="keywordflow">return</span> -1;</div><div class="line">    };</div><div class="line"></div><div class="line">    <span class="keywordtype">int</span> camera_device = parser.get&lt;<span class="keywordtype">int</span>&gt;(<span class="stringliteral">&quot;camera&quot;</span>);</div><div class="line">    <a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html">VideoCapture</a> capture;</div><div class="line">    <span class="comment">//-- 2. Read the video stream</span></div><div class="line">    capture.<a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html#a614a1702e15f42ede5100014ce7f48ed">open</a>( camera_device );</div><div class="line">    <span class="keywordflow">if</span> ( ! capture.isOpened() )</div><div class="line">    {</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;--(!)Error opening video capture\n&quot;</span>;</div><div class="line">        <span class="keywordflow">return</span> -1;</div><div class="line">    }</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> frame;</div><div class="line">    <span class="keywordflow">while</span> ( capture.read(frame) )</div><div class="line">    {</div><div class="line">        <span class="keywordflow">if</span>( frame.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abbec3525a852e77998aba034813fded4">empty</a>() )</div><div class="line">        {</div><div class="line">            cout &lt;&lt; <span class="stringliteral">&quot;--(!) No captured frame -- Break!\n&quot;</span>;</div><div class="line">            <span class="keywordflow">break</span>;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">//-- 3. Apply the classifier to the frame</span></div><div class="line">        detectAndDisplay( frame );</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span>( <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">waitKey</a>(10) == 27 )</div><div class="line">        {</div><div class="line">            <span class="keywordflow">break</span>; <span class="comment">// escape</span></div><div class="line">        }</div><div class="line">    }</div><div class="line">    <span class="keywordflow">return</span> 0;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> detectAndDisplay( <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> frame )</div><div class="line">{</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> frame_gray;</div><div class="line">    <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cvtColor</a>( frame, frame_gray, <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0a353a4b8db9040165db4dacb5bcefb6ea">COLOR_BGR2GRAY</a> );</div><div class="line">    <a class="code" href="../../d6/dc7/group__imgproc__hist.html#ga7e54091f0c937d49bf84152a16f76d6e">equalizeHist</a>( frame_gray, frame_gray );</div><div class="line"></div><div class="line">    <span class="comment">//-- Detect faces</span></div><div class="line">    std::vector&lt;Rect&gt; faces;</div><div class="line">    face_cascade.<a class="code" href="../../d1/de5/classcv_1_1CascadeClassifier.html#aaf8181cb63968136476ec4204ffca498">detectMultiScale</a>( frame_gray, faces );</div><div class="line"></div><div class="line">    <span class="keywordflow">for</span> ( <span class="keywordtype">size_t</span> i = 0; i &lt; faces.size(); i++ )</div><div class="line">    {</div><div class="line">        <a class="code" href="../../db/d4e/classcv_1_1Point__.html">Point</a> center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );</div><div class="line">        <a class="code" href="../../d6/d6e/group__imgproc__draw.html#ga28b2267d35786f5f890ca167236cbc69">ellipse</a>( frame, center, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>( 255, 0, 255 ), 4 );</div><div class="line"></div><div class="line">        <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> faceROI = frame_gray( faces[i] );</div><div class="line"></div><div class="line">        <span class="comment">//-- In each face, detect eyes</span></div><div class="line">        std::vector&lt;Rect&gt; eyes;</div><div class="line">        eyes_cascade.<a class="code" href="../../d1/de5/classcv_1_1CascadeClassifier.html#aaf8181cb63968136476ec4204ffca498">detectMultiScale</a>( faceROI, eyes );</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> ( <span class="keywordtype">size_t</span> j = 0; j &lt; eyes.size(); j++ )</div><div class="line">        {</div><div class="line">            <a class="code" href="../../db/d4e/classcv_1_1Point__.html">Point</a> eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );</div><div class="line">            <span class="keywordtype">int</span> radius = <a class="code" href="../../db/de0/group__core__utils.html#ga085eca238176984a0b72df2818598d85">cvRound</a>( (eyes[j].width + eyes[j].height)*0.25 );</div><div class="line">            <a class="code" href="../../d9/db7/group__datasets__gr.html#gga610754124ced68d1f05760b5948fbb76a6f0d8b2d9e3e947b2a5c1eff9e81ee95">circle</a>( frame, eye_center, radius, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>( 255, 0, 0 ), 4 );</div><div class="line">        }</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">//-- Show what you got</span></div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( <span class="stringliteral">&quot;Capture - Face detection&quot;</span>, frame );</div><div class="line">}</div></div><!-- fragment -->  </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'><p> This tutorial code's is shown lines below. You can also download it from <a href="https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/objectDetection/cascade_classifier/ObjectDetectionDemo.java">here</a> </p><div class="fragment"><div class="line"><span class="keyword">import</span> java.util.List;</div><div class="line"></div><div class="line"><span class="keyword">import</span> org.opencv.core.Core;</div><div class="line"><span class="keyword">import</span> org.opencv.core.Mat;</div><div class="line"><span class="keyword">import</span> org.opencv.core.MatOfRect;</div><div class="line"><span class="keyword">import</span> org.opencv.core.Point;</div><div class="line"><span class="keyword">import</span> org.opencv.core.Rect;</div><div class="line"><span class="keyword">import</span> org.opencv.core.Scalar;</div><div class="line"><span class="keyword">import</span> org.opencv.core.Size;</div><div class="line"><span class="keyword">import</span> org.opencv.highgui.HighGui;</div><div class="line"><span class="keyword">import</span> org.opencv.imgproc.Imgproc;</div><div class="line"><span class="keyword">import</span> org.opencv.objdetect.CascadeClassifier;</div><div class="line"><span class="keyword">import</span> org.opencv.videoio.VideoCapture;</div><div class="line"></div><div class="line"><span class="keyword">class </span>ObjectDetection {</div><div class="line">    <span class="keyword">public</span> <span class="keywordtype">void</span> detectAndDisplay(Mat frame, CascadeClassifier faceCascade, CascadeClassifier eyesCascade) {</div><div class="line">        Mat frameGray = <span class="keyword">new</span> Mat();</div><div class="line">        Imgproc.cvtColor(frame, frameGray, Imgproc.COLOR_BGR2GRAY);</div><div class="line">        Imgproc.equalizeHist(frameGray, frameGray);</div><div class="line"></div><div class="line">        <span class="comment">// -- Detect faces</span></div><div class="line">        MatOfRect faces = <span class="keyword">new</span> MatOfRect();</div><div class="line">        faceCascade.detectMultiScale(frameGray, faces);</div><div class="line"></div><div class="line">        List&lt;Rect&gt; listOfFaces = faces.toList();</div><div class="line">        <span class="keywordflow">for</span> (<a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a> face : listOfFaces) {</div><div class="line">            <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a> center = <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(face.x + face.width / 2, face.y + face.height / 2);</div><div class="line">            Imgproc.ellipse(frame, center, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(face.width / 2, face.height / 2), 0, 0, 360,</div><div class="line">                    <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>(255, 0, 255));</div><div class="line"></div><div class="line">            Mat faceROI = frameGray.submat(face);</div><div class="line"></div><div class="line">            <span class="comment">// -- In each face, detect eyes</span></div><div class="line">            MatOfRect eyes = <span class="keyword">new</span> MatOfRect();</div><div class="line">            eyesCascade.detectMultiScale(faceROI, eyes);</div><div class="line"></div><div class="line">            List&lt;Rect&gt; listOfEyes = eyes.toList();</div><div class="line">            <span class="keywordflow">for</span> (<a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a> eye : listOfEyes) {</div><div class="line">                <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a> eyeCenter = <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(face.x + eye.x + eye.width / 2, face.y + eye.y + eye.height / 2);</div><div class="line">                <span class="keywordtype">int</span> radius = (int) Math.round((eye.width + eye.height) * 0.25);</div><div class="line">                Imgproc.circle(frame, eyeCenter, radius, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>(255, 0, 0), 4);</div><div class="line">            }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">//-- Show what you got</span></div><div class="line">        HighGui.imshow(<span class="stringliteral">&quot;Capture - Face detection&quot;</span>, frame );</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keyword">public</span> <span class="keywordtype">void</span> run(<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>[] args) {</div><div class="line">        <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> filenameFaceCascade = args.length &gt; 2 ? args[0] : <span class="stringliteral">&quot;../../data/haarcascades/haarcascade_frontalface_alt.xml&quot;</span>;</div><div class="line">        <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> filenameEyesCascade = args.length &gt; 2 ? args[1] : <span class="stringliteral">&quot;../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml&quot;</span>;</div><div class="line">        <span class="keywordtype">int</span> cameraDevice = args.length &gt; 2 ? Integer.parseInt(args[2]) : 0;</div><div class="line"></div><div class="line">        CascadeClassifier faceCascade = <span class="keyword">new</span> CascadeClassifier();</div><div class="line">        CascadeClassifier eyesCascade = <span class="keyword">new</span> CascadeClassifier();</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (!faceCascade.load(filenameFaceCascade)) {</div><div class="line">            System.err.println(<span class="stringliteral">&quot;--(!)Error loading face cascade: &quot;</span> + filenameFaceCascade);</div><div class="line">            System.exit(0);</div><div class="line">        }</div><div class="line">        <span class="keywordflow">if</span> (!eyesCascade.load(filenameEyesCascade)) {</div><div class="line">            System.err.println(<span class="stringliteral">&quot;--(!)Error loading eyes cascade: &quot;</span> + filenameEyesCascade);</div><div class="line">            System.exit(0);</div><div class="line">        }</div><div class="line"></div><div class="line">        VideoCapture capture = <span class="keyword">new</span> VideoCapture(cameraDevice);</div><div class="line">        <span class="keywordflow">if</span> (!capture.isOpened()) {</div><div class="line">            System.err.println(<span class="stringliteral">&quot;--(!)Error opening video capture&quot;</span>);</div><div class="line">            System.exit(0);</div><div class="line">        }</div><div class="line"></div><div class="line">        Mat frame = <span class="keyword">new</span> Mat();</div><div class="line">        <span class="keywordflow">while</span> (capture.read(frame)) {</div><div class="line">            <span class="keywordflow">if</span> (frame.empty()) {</div><div class="line">                System.err.println(<span class="stringliteral">&quot;--(!) No captured frame -- Break!&quot;</span>);</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line">            }</div><div class="line"></div><div class="line">            <span class="comment">//-- 3. Apply the classifier to the frame</span></div><div class="line">            detectAndDisplay(frame, faceCascade, eyesCascade);</div><div class="line"></div><div class="line">            <span class="keywordflow">if</span> (HighGui.waitKey(10) == 27) {</div><div class="line">                <span class="keywordflow">break</span>;<span class="comment">// escape</span></div><div class="line">            }</div><div class="line">        }</div><div class="line"></div><div class="line">        System.exit(0);</div><div class="line">    }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="keyword">class </span>ObjectDetectionDemo {</div><div class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keywordtype">void</span> main(<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>[] args) {</div><div class="line">        <span class="comment">// Load the native OpenCV library</span></div><div class="line">        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);</div><div class="line"></div><div class="line">        <span class="keyword">new</span> ObjectDetection().run(args);</div><div class="line">    }</div><div class="line">}</div></div><!-- fragment -->  </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'><p> This tutorial code's is shown lines below. You can also download it from <a href="https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/objectDetection/cascade_classifier/objectDetection.py">here</a> </p><div class="fragment"><div class="line"><span class="keyword">from</span> __future__ <span class="keyword">import</span> print_function</div><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"><span class="keyword">import</span> argparse</div><div class="line"></div><div class="line"><span class="keyword">def </span>detectAndDisplay(frame):</div><div class="line">    frame_gray = <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cv.cvtColor</a>(frame, cv.COLOR_BGR2GRAY)</div><div class="line">    frame_gray = <a class="code" href="../../d6/dc7/group__imgproc__hist.html#ga7e54091f0c937d49bf84152a16f76d6e">cv.equalizeHist</a>(frame_gray)</div><div class="line"></div><div class="line">    <span class="comment">#-- Detect faces</span></div><div class="line">    faces = face_cascade.detectMultiScale(frame_gray)</div><div class="line">    <span class="keywordflow">for</span> (x,y,w,h) <span class="keywordflow">in</span> faces:</div><div class="line">        center = (x + w//2, y + h//2)</div><div class="line">        frame = <a class="code" href="../../d6/d6e/group__imgproc__draw.html#ga57be400d8eff22fb946ae90c8e7441f9">cv.ellipse</a>(frame, center, (w//2, h//2), 0, 0, 360, (255, 0, 255), 4)</div><div class="line"></div><div class="line">        faceROI = frame_gray[y:y+h,x:x+w]</div><div class="line">        <span class="comment">#-- In each face, detect eyes</span></div><div class="line">        eyes = eyes_cascade.detectMultiScale(faceROI)</div><div class="line">        <span class="keywordflow">for</span> (x2,y2,w2,h2) <span class="keywordflow">in</span> eyes:</div><div class="line">            eye_center = (x + x2 + w2//2, y + y2 + h2//2)</div><div class="line">            radius = int(round((w2 + h2)*0.25))</div><div class="line">            frame = <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670">cv.circle</a>(frame, eye_center, radius, (255, 0, 0 ), 4)</div><div class="line"></div><div class="line">    <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(<span class="stringliteral">&#39;Capture - Face detection&#39;</span>, frame)</div><div class="line"></div><div class="line">parser = argparse.ArgumentParser(description=<span class="stringliteral">&#39;Code for Cascade Classifier tutorial.&#39;</span>)</div><div class="line">parser.add_argument(<span class="stringliteral">&#39;--face_cascade&#39;</span>, help=<span class="stringliteral">&#39;Path to face cascade.&#39;</span>, default=<span class="stringliteral">&#39;data/haarcascades/haarcascade_frontalface_alt.xml&#39;</span>)</div><div class="line">parser.add_argument(<span class="stringliteral">&#39;--eyes_cascade&#39;</span>, help=<span class="stringliteral">&#39;Path to eyes cascade.&#39;</span>, default=<span class="stringliteral">&#39;data/haarcascades/haarcascade_eye_tree_eyeglasses.xml&#39;</span>)</div><div class="line">parser.add_argument(<span class="stringliteral">&#39;--camera&#39;</span>, help=<span class="stringliteral">&#39;Camera divide number.&#39;</span>, type=int, default=0)</div><div class="line">args = parser.parse_args()</div><div class="line"></div><div class="line">face_cascade_name = args.face_cascade</div><div class="line">eyes_cascade_name = args.eyes_cascade</div><div class="line"></div><div class="line">face_cascade = <a class="code" href="../../d1/de5/classcv_1_1CascadeClassifier.html">cv.CascadeClassifier</a>()</div><div class="line">eyes_cascade = <a class="code" href="../../d1/de5/classcv_1_1CascadeClassifier.html">cv.CascadeClassifier</a>()</div><div class="line"></div><div class="line"><span class="comment">#-- 1. Load the cascades</span></div><div class="line"><span class="keywordflow">if</span> <span class="keywordflow">not</span> face_cascade.load(<a class="code" href="../../d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13">cv.samples.findFile</a>(face_cascade_name)):</div><div class="line">    <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&#39;--(!)Error loading face cascade&#39;</span>)</div><div class="line">    exit(0)</div><div class="line"><span class="keywordflow">if</span> <span class="keywordflow">not</span> eyes_cascade.load(<a class="code" href="../../d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13">cv.samples.findFile</a>(eyes_cascade_name)):</div><div class="line">    <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&#39;--(!)Error loading eyes cascade&#39;</span>)</div><div class="line">    exit(0)</div><div class="line"></div><div class="line">camera_device = args.camera</div><div class="line"><span class="comment">#-- 2. Read the video stream</span></div><div class="line">cap = <a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html">cv.VideoCapture</a>(camera_device)</div><div class="line"><span class="keywordflow">if</span> <span class="keywordflow">not</span> cap.isOpened:</div><div class="line">    <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&#39;--(!)Error opening video capture&#39;</span>)</div><div class="line">    exit(0)</div><div class="line"></div><div class="line"><span class="keywordflow">while</span> <span class="keyword">True</span>:</div><div class="line">    ret, frame = cap.read()</div><div class="line">    <span class="keywordflow">if</span> frame <span class="keywordflow">is</span> <span class="keywordtype">None</span>:</div><div class="line">        <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&#39;--(!) No captured frame -- Break!&#39;</span>)</div><div class="line">        <span class="keywordflow">break</span></div><div class="line"></div><div class="line">    detectAndDisplay(frame)</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv.waitKey</a>(10) == 27:</div><div class="line">        <span class="keywordflow">break</span></div></div><!-- fragment -->  </div> <h2>Result </h2>
<ol type="1">
<li><p class="startli">Here is the result of running the code above and using as input the video stream of a built-in webcam:</p>
<div class="image">
<img src="../../Cascade_Classifier_Tutorial_Result_Haar.jpg" alt="Cascade_Classifier_Tutorial_Result_Haar.jpg"/>
</div>
<p class="startli">Be sure the program will find the path of files <em>haarcascade_frontalface_alt.xml</em> and <em>haarcascade_eye_tree_eyeglasses.xml</em>. They are located in <em>opencv/data/haarcascades</em></p>
</li>
<li><p class="startli">This is the result of using the file <em>lbpcascade_frontalface.xml</em> (LBP trained) for the face detection. For the eyes we keep using the file used in the tutorial.</p>
<div class="image">
<img src="../../Cascade_Classifier_Tutorial_Result_LBP.jpg" alt="Cascade_Classifier_Tutorial_Result_LBP.jpg"/>
</div>
</li>
</ol>
<h2>Additional Resources </h2>
<ol type="1">
<li>Paul Viola and Michael J. Jones. Robust real-time face detection. International Journal of Computer Vision, 57(2):137–154, 2004. <a class="el" href="../../d0/de3/citelist.html#CITEREF_Viola04">[261]</a></li>
<li>Rainer Lienhart and Jochen Maydt. An extended set of haar-like features for rapid object detection. In Image Processing. 2002. Proceedings. 2002 International Conference on, volume 1, pages I–900. IEEE, 2002. <a class="el" href="../../d0/de3/citelist.html#CITEREF_Lienhart02">[149]</a></li>
<li>Video Lecture on <a href="https://www.youtube.com/watch?v=WfdYYNamHZ8">Face Detection and Tracking</a></li>
<li>An interesting interview regarding Face Detection by <a href="https://web.archive.org/web/20171204220159/http://www.makematics.com/research/viola-jones/">Adam Harvey</a></li>
<li><a href="https://vimeo.com/12774628">OpenCV Face Detection: Visualized</a> on Vimeo by Adam Harvey </li>
</ol>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:37 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
